//Listing 4. Simple Sound Recording
 
 
/*
 
This example reads from the default PCM device
and writes to standard output for 5 seconds of data.
 
*/
 
/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API
 
#include <alsa/asoundlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <speex/speex.h>

#define TO_PORT 12345
#define TO_ADDR "192.168.2.234"

/*Holds the state of the encoder*/
void *state;
/*Holds bits so they can be read and written to by the Speex routines*/
SpeexBits bits;

/*The frame size in hardcoded for this sample code but it doesn't have to be*/
#define FRAME_SIZE 160

short in[FRAME_SIZE];
float input[FRAME_SIZE];
char cbits[200];
int nbBytes;
   int i, tmp;
FILE *fout;
   
struct sockaddr_in addr;
int fd;
     
void init_udp()
{
     /* create what looks like an ordinary UDP socket */
     if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) 
     {
				perror("socket");
				exit(1);
     }

     /* set up destination address */
     memset(&addr,0,sizeof(addr));
     addr.sin_family=AF_INET;
     addr.sin_addr.s_addr=inet_addr(TO_ADDR);
     addr.sin_port=htons(TO_PORT);
}

int main(int argc, char **argv) {
long loops;
int rc;
int size;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
unsigned int val;
int dir;
snd_pcm_uframes_t frames;
char *buffer;
   char *inFile, *outFile;
   
   outFile = argv[1];
   fout = fopen(outFile, "wb");
   
init_udp();
 
 
    /*Create a new encoder state in narrowband mode*/
   state = speex_encoder_init(&speex_nb_mode);

   /*Set the quality to 8 (15 kbps)*/
   tmp=8;
   speex_encoder_ctl(state, SPEEX_SET_QUALITY, &tmp);
   
   /*Initialization of the structure that holds the bits*/
   speex_bits_init(&bits);
      
/* Open PCM device for recording (capture). */
rc = snd_pcm_open(&handle, "default",
                    SND_PCM_STREAM_CAPTURE, 0);
if (rc < 0) {
    fprintf(stderr,
            "unable to open pcm device: %s\n",
            snd_strerror(rc));
    exit(1);
}
 
/* Allocate a hardware parameters object. */
snd_pcm_hw_params_alloca(&params);
 
/* Fill it in with default values. */
snd_pcm_hw_params_any(handle, params);
 
/* Set the desired hardware parameters. */
 
/* Interleaved mode */
snd_pcm_hw_params_set_access(handle, params,
                      SND_PCM_ACCESS_RW_INTERLEAVED);
 
/* Signed 16-bit little-endian format */
snd_pcm_hw_params_set_format(handle, params,
                              SND_PCM_FORMAT_S16_LE);
 
/* Two channels (stereo) */
snd_pcm_hw_params_set_channels(handle, params, 1);
 
/* 44100 bits/second sampling rate (CD quality) */
val = 8000;
snd_pcm_hw_params_set_rate_near(handle, params,
                                  &val, &dir);
 
/* Set period size to 32 frames. */
frames = 160;
snd_pcm_hw_params_set_period_size_near(handle,
                              params, &frames, &dir);
 
/* Write the parameters to the driver */
rc = snd_pcm_hw_params(handle, params);
if (rc < 0) {
    fprintf(stderr,
            "unable to set hw parameters: %s\n",
            snd_strerror(rc));
    exit(1);
}
 
/* Use a buffer large enough to hold one period */
snd_pcm_hw_params_get_period_size(params,
                                      &frames, &dir);
size = frames * 2; /* 2 bytes/sample, 2 channels */
buffer = (char *) malloc(size);
 
/* We want to loop for 5 seconds */
snd_pcm_hw_params_get_period_time(params,
                                         &val, &dir);
loops = 50000000L / val;
 
//while (loops > 0) {
while(1)
{
    //loops--;
    printf(".");
    rc = snd_pcm_readi(handle, buffer, frames);
    if (rc == -EPIPE) {
      /* EPIPE means overrun */
      fprintf(stderr, "overrun occurred\n");
      snd_pcm_prepare(handle);
    } else if (rc < 0) {
      fprintf(stderr,
              "error from read: %s\n",
              snd_strerror(rc));
    } else if (rc != (int)frames) {
      fprintf(stderr, "short read, read %d frames\n", rc);
    }
    //rc = write(1, buffer, size);
    
    
    #if 1
    //printf("aaaaaaaaaaaaaa\n");
      /*Copy the 16 bits values to float so Speex can work on them*/
      for (i=0;i<FRAME_SIZE;i++)
         input[i] = ((short*)buffer)[i];//in[i];
    //printf("bbbbbbb\n");
      /*Flush all the bits in the struct so we can encode a new frame*/
      speex_bits_reset(&bits);
    //printf("cccccccccc\n");
      /*Encode the frame*/
      speex_encode(state, input, &bits);
    //printf("ddddddd\n");            
      /*Copy the bits to an array of char that can be written*/
      nbBytes = speex_bits_write(&bits, cbits, 200);
    //printf("eeeeeeeeeeeeeeeeeeeeeeeeeee\n");      
    #endif  
      
#if 0
      /*Write the size of the frame first. This is what sampledec expects but
       it's likely to be different in your own application*/
      fwrite(&nbBytes, sizeof(int), 1, fout);
      /*Write the compressed data*/
      fwrite(cbits, 1, nbBytes, fout);
#endif
                
	if ((rc=sendto(fd, cbits, nbBytes, 0, (struct sockaddr *) &addr, sizeof(addr))) < 0) 
	{
		   perror("sendto");
		   exit(1);
	}	
				    
    if (rc != nbBytes)
      fprintf(stderr,
              "short write: wrote %d bytes\n", rc);
}
 
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
 
return 0;
}

